﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace V32VM
{
    public partial class WatchEditDialog : Form
    {
        private bool validated { get; set; }
        private bool cancelling { get; set; }

        private bool Editing { get; set; }
        private Source OriginalSource { get; set; }

        private string WatchName { get; set; }
        private Source Source { get; set; }
        private bool IsAddressWatch
        {
            get;
            set;
        }
        private bool IsValueWatch
        {
            get { return !IsAddressWatch; }
            set { IsAddressWatch = !IsValueWatch; }
        }
        private bool IsWord { get; set; }

        public Watch Watch { get; private set; }

        public WatchEditDialog()
        {
            InitializeComponent();
            Editing = false;
            Text = "Add Watch";

            watchTypeListBox.SelectedIndex = 0;
            addressWatchSizeListBox.SelectedIndex = 0;
        }
        public WatchEditDialog(Watch original)
            : this()
        {
            Editing = true;
            Text = "Edit Watch";
            nameTextBox.Enabled = false;
            OriginalSource = original.Source;

            nameTextBox.Text = original.Name;
            sourceTextBox.Text = original.Source.ToParsableString();
            watchTypeListBox.SelectedIndex = original.IsAddressWatch ? 0 : 1;
            addressWatchSizeListBox.SelectedIndex = original.IsWord ? 1 : 0;
        }

        private void watchTypeListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            addressWatchSizeListBox.Enabled = IsAddressWatch =
                watchTypeListBox.SelectedItem.ToString().Contains("Address");
        }

        private void okButton_Click(object sender, EventArgs e)
        {
            validated = false;

            this.WatchName = nameTextBox.Text;
            bool nameOK = true;
            bool nameMatches = System.Text.RegularExpressions.Regex.IsMatch(this.WatchName, "[a-zA-Z_][a-zA-Z0-9_]*");
            if (nameMatches)
            {
                try { Registers.FromString(this.WatchName); nameOK = false; }
                catch { }
            }
            else
                nameOK = false;

            if (!Editing)
                foreach (string name in (from watch in Watch.Watches select watch.Name))
                    if (this.WatchName == name)
                    {
                        nameOK = false;
                        break;
                    }

            if (!nameOK)
            {
                MessageBox.Show("A watch name must be a unique and valid identifier and must not be a register name.",
                    "Name Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            try { this.Source = V32VM.Source.Parse(this.sourceTextBox.Text); }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Source Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (Editing)
            {
                Watch[] fakeWatches = (from w in Watch.Watches
                                       select w.Name == this.WatchName ?
                                           new Watch(w.Name, this.Source) : w).ToArray();
                if (this.Source.IsRecursive(fakeWatches))
                {
                    MessageBox.Show("Watches may not be self-recursive or mutually recursive.", "Recursion Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }

            this.IsWord = addressWatchSizeListBox.SelectedItem.ToString() == "Word";
            this.Watch = IsAddressWatch ? new Watch(WatchName, Source, IsWord) : new Watch(WatchName, Source);
            validated = true;
        }

        private void cancelButton_Click(object sender, EventArgs e)
        {
            cancelling = true;
        }

        private void WatchEditDialog_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!validated && !cancelling)
                e.Cancel = true;
        }
    }
}
